package org.modelcc.io.java.processor;

import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.modelcc.Pattern;
import org.modelcc.io.java.JavaLanguageClass;
import org.modelcc.io.java.JavaModelProcessor;
import org.modelcc.io.java.JavaModelReader;
import org.modelcc.io.java.JavaLanguageMetadata;
import org.modelcc.io.java.Reflection;
import org.modelcc.language.metamodel.LanguageMember;

/**
 * Process member inheritance
 */
public class MemberInheritanceProcessor extends JavaModelProcessor<JavaLanguageMetadata>
{	
	public MemberInheritanceProcessor (JavaModelReader reader)
	{
		super(reader);
	}
	
	@Override
	public void process(JavaLanguageMetadata metadata) 
	{
    	Set<JavaLanguageClass> elements = metadata.getJavaElements();
    	Map<JavaLanguageClass,Set<JavaLanguageClass>> subclasses = metadata.getJavaSubclasses(); 
    	
    	JavaLanguageClass source;
    	JavaLanguageClass target;
    	Iterator<JavaLanguageClass> it1 = elements.iterator();
    	while (it1.hasNext()) {
    		source = it1.next();
    		if (!Reflection.hasAnnotation(source.getElementClass(), Pattern.class)) {
    			Iterator<JavaLanguageClass> ite;
    			if (subclasses.get(source) != null) {
    				ite = subclasses.get(source).iterator();
    				while (ite.hasNext()) {
    					target = ite.next();
    					inheritMemberClass(subclasses,source,target);
    				}
    			}
    		}
    	}		
    }
	
    /**
     * Inherits members from a source to a target element
     * @param subclasses the subclasses map
     * @param source the source element
     * @param target the target element
     */
    private void inheritMemberClass (
    		Map<JavaLanguageClass,Set<JavaLanguageClass>> subclasses,
    		JavaLanguageClass source,
    		JavaLanguageClass target) 
    {
    	Iterator<JavaLanguageClass> ite;
    	JavaLanguageClass target2;

    	int j = 0;
    	for (int i = 0;i < source.getMembers().size();i++) {
    		LanguageMember content = source.getMember(i);
    		if (!target.getMembers().contains(content)) {
    			target.getMembers().add(j,content);
    			j++;
    		}
    	}
    	if (subclasses.get(target) != null) {
    		ite = subclasses.get(target).iterator();
    		while (ite.hasNext()) {
    			target2 = ite.next();
    			inheritMemberClass(subclasses,target,target2);
    		}
    	}
    }
	
}
